/* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
/* Copyright (C) 2012 Zongyou Yao. All rights reserved.     */

#ifndef RING_INCLUDED
#define RING_INCLUDED

/**
 * Ring indices run from zero to N - 1, where N is the length of the ring. The 
 * empty ring has no elements. Pointers can be added or removed anywhere; rings
 * expand automatically. Rotating a ring changes its origin. It is a checked 
 * runtime error to pass a null ring_t to any ring function.
 */
typedef struct ring_t * ring_t;

/**
 * Creates and returns an empty ring.
 * Exception mem_failed can be raised.
 */
ring_t ring_new(void);

/**
 * Creates and returns a ring whose elements are the "..." arguments up to the 
 * first null pointer.
 * Exception mem_failed can be raised.
 */
ring_t ring_ring(void *x, ...);

/**
 * Deallocates and clears *ring. It is a checked runtime error for ring or *ring
 * to be null.
 */
void ring_free(ring_t *ring);

/**
 * Returns the number of elements in ring.
 */
int ring_length(ring_t ring);

/**
 * Returns the ith element in ring. It is a checked runtime error for i < 0 or i >= N,
 * where N is the length of ring.
 */
void *ring_get(ring_t ring, int i);

/**
 * Changes the ith element in ring to x and returns the previous value.
 * See ring_get for checked runtime error.
 * Exception mem_failed can be raised.
 */
void *ring_put(ring_t ring, int i, void *x);

/**
 * Inserts x at position pos in ring and returns x. Positions identify points 
 * between elements; see str. It is a checked runtime error for pos < -N or
 * pos > N + 1, where N is the length of ring.
 * Exception mem_failed can be raised.
 */
void *ring_add(ring_t ring, int pos, void *x);

/**
 * Adds x to the low (index 0) end of ring and returns x.
 * Exception mem_failed can be raised.
 */
void *ring_addlo(ring_t ring, void *x);

/**
 * Adds x to the high (index N - 1) end of ring and returns x.
 * Exception mem_failed can be raised.
 */
void *ring_addhi(ring_t ring, void *x);

/**
 * Removes and returns element i from ring. It is a checked runtime error for 
 * i < 0 or i >= N, where N is the length of ring.
 */
void *ring_remove(ring_t ring, int i);

/**
 * Removes and returns the element at the low end (index 0) of ring. 
 * It is a checked runtime error for ring to be empty.
 */
void *ring_remlo(ring_t ring);

/**
 * Removes and returns the element at the high end (index N - 1) of ring. 
 * It is a checked runtime error for ring to be empty.
 */
void *ring_remhi(ring_t ring);

/**
 * Rotates the origin of ring n elements left (n < 0) or right (n >= 0). It is
 * a checked runtime error for |n| < 0 or |n| > N, where N is the length of ring.
 */
void ring_rotate(ring_t ring, int n);

#endif
